package com.wits.util;

import android.os.Handler;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by zhengboyuan on 2017-01-17.
 */

public class HandlerTimer {

    public static final long INVALID_TIMER = 0;


    public long delay(long delayMillis, Runnable runnable) {
        if (runnable == null) {
            return INVALID_TIMER;
        }

        long id = makeTimerId();
        TimerRunnable timerRunnable = new TimerRunnable(id, delayMillis, runnable, false);
        timerRunnable.setup();
        timerRunnableMap.put(id, timerRunnable);

        return id;
    }

    public long setTimer(long delayMillis, Runnable runnable) {
        if (runnable == null) {
            return INVALID_TIMER;
        }

        long id = makeTimerId();
        TimerRunnable timerRunnable = new TimerRunnable(id, delayMillis, runnable, true);
        timerRunnable.setup();
        timerRunnableMap.put(id, timerRunnable);

        return id;
    }

    public void cancel(long timerId) {
        TimerRunnable timerRunnable = timerRunnableMap.remove(timerId);
        if (timerRunnable != null) {
            timerRunnable.teardown();
        }
    }

    /**
     * cancel all timer
     */
    public void cancel() {
        Iterator<Map.Entry<Long, TimerRunnable>> it = timerRunnableMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Long, TimerRunnable> entry = it.next();
            entry.getValue().teardown();
            it.remove();
        }
    }


    public HandlerTimer() {

    }

    long makeTimerId() {
        synchronized (this) {
            timerId ++;
            return timerId;
        }
    }


    class TimerRunnable implements Runnable {

        long id;
        long delay;
        Runnable runnable;
        boolean isPeriod;
        Handler handler;

        public TimerRunnable(long id, long delay, Runnable runnable, boolean isPeriod) {
            this.id = id;
            this.delay = delay;
            this.runnable = runnable;
            this.isPeriod = isPeriod;
            this.handler = new Handler();
        }

        @Override
        public void run() {
            this.runnable.run();

            if (isPeriod) {
                setup();
            } else {
                cancel(id);
            }
        }

        public void setup() {
            this.handler.postDelayed(this, delay);
        }

        public void teardown() {
            this.handler.removeCallbacks(this);
        }

        public boolean isPeriod() {
            return this.isPeriod;
        }


    }

    private static long timerId = 0;
    private Map< Long, TimerRunnable > timerRunnableMap = new ConcurrentHashMap<>();


}
